<template>
  <div
    id="code-editor"
    ref="codeEditorRef"
    style="min-height: 400px; height: 60vh"
  />
  <!--  <a-button @click="fillValue">填充值</a-button>-->
</template>

<script setup lang="ts">
import * as monaco from "monaco-editor";
import { onMounted, ref, toRaw, withDefaults, defineProps, watch } from "vue";

/**
 * 定义组件属性类型
 */
interface Props {
  value: string;
  language?: string;
  handleChange: (v: string) => void;
}

/**
 * 给组件指定初始值
 */
const props = withDefaults(defineProps<Props>(), {
  value: () => "",
  language: () => "java",
  handleChange: (v: string) => {
    console.log(v);
  },
});

const codeEditorRef = ref();
const codeEditor = ref();

// const fillValue = () => {
//   if (!codeEditor.value) {
//     return;
//   }
//   // 改变值
//   toRaw(codeEditor.value).setValue("新的值");
// };

watch(
  () => props.language,
  () => {
    if (codeEditor.value) {
      monaco.editor.setModelLanguage(
        toRaw(codeEditor.value).getModel(),
        props.language
      );
    }
  }
);

onMounted(() => {
  if (!codeEditorRef.value) {
    return;
  }

  // TODO 注册 Java 常用包的代码片段补全
  monaco.languages.registerCompletionItemProvider("java", {
    provideCompletionItems: (model, position) => {
      const word = model.getWordUntilPosition(position);
      const range = {
        startLineNumber: position.lineNumber,
        endLineNumber: position.lineNumber,
        startColumn: word.startColumn,
        endColumn: word.endColumn,
      };
      const suggestions = [
        {
          label: "ArrayList (带 import)",
          kind: monaco.languages.CompletionItemKind.Class,
          insertText:
            "import java.util.ArrayList;\nArrayList<${1:Type}> ${2:list} = new ArrayList<>();",
          insertTextRules:
            monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          documentation: "动态数组，片段自带 import，需手动剪切到顶部",
          range: range,
        },
        {
          label: "HashMap (带 import)",
          kind: monaco.languages.CompletionItemKind.Class,
          insertText:
            "import java.util.HashMap;\nHashMap<${1:KeyType}, ${2:ValueType}> ${3:map} = new HashMap<>();",
          insertTextRules:
            monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          documentation: "哈希映射，片段自带 import，需手动剪切到顶部",
          range: range,
        },
        {
          label: "Scanner (带 import)",
          kind: monaco.languages.CompletionItemKind.Class,
          insertText:
            "import java.util.Scanner;\nScanner ${1:scanner} = new Scanner(System.in);",
          insertTextRules:
            monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          documentation: "输入扫描器，片段自带 import，需手动剪切到顶部",
          range: range,
        },
        {
          label: "Arrays.sort (带 import)",
          kind: monaco.languages.CompletionItemKind.Function,
          insertText: "import java.util.Arrays;\nArrays.sort(${1:array});",
          insertTextRules:
            monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          documentation: "数组排序，片段自带 import，需手动剪切到顶部",
          range: range,
        },
        {
          label: "System.out.println",
          kind: monaco.languages.CompletionItemKind.Function,
          insertText: "System.out.println(${1:value});",
          insertTextRules:
            monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          documentation: "打印输出到控制台",
          range: range,
        },
        {
          label: "Math.max",
          kind: monaco.languages.CompletionItemKind.Function,
          insertText: "Math.max(${1:a}, ${2:b});",
          insertTextRules:
            monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          documentation: "返回两个数中的最大值",
          range: range,
        },
        {
          label: "Math.min",
          kind: monaco.languages.CompletionItemKind.Function,
          insertText: "Math.min(${1:a}, ${2:b});",
          insertTextRules:
            monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          documentation: "返回两个数中的最小值",
          range: range,
        },
        {
          label: "String.valueOf",
          kind: monaco.languages.CompletionItemKind.Function,
          insertText: "String.valueOf(${1:value});",
          insertTextRules:
            monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          documentation: "将值转换为字符串",
          range: range,
        },
        {
          label: "Integer.parseInt",
          kind: monaco.languages.CompletionItemKind.Function,
          insertText: "Integer.parseInt(${1:str});",
          insertTextRules:
            monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          documentation: "将字符串转换为整数",
          range: range,
        },
        {
          label: "Long.parseLong",
          kind: monaco.languages.CompletionItemKind.Function,
          insertText: "Long.parseLong(${1:str});",
          insertTextRules:
            monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          documentation: "将字符串转换为长整数",
          range: range,
        },
      ];
      return { suggestions };
    },
  });

  // Hover on each property to see its docs!
  codeEditor.value = monaco.editor.create(codeEditorRef.value, {
    value: props.value,
    language: props.language,
    automaticLayout: true,
    colorDecorators: true,
    minimap: {
      enabled: true,
    },
    readOnly: false,
    theme: "vs-dark",
    // lineNumbers: "off",
    // roundedSelection: false,
    // scrollBeyondLastLine: false,
  });

  // 编辑 监听内容变化
  codeEditor.value.onDidChangeModelContent(() => {
    props.handleChange(toRaw(codeEditor.value).getValue());
  });
});
</script>

<style scoped></style>
